package 反射;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

//《Java Method类》
//Method类位于java.lang.reflect包下,在Java反射中Method类描述的是类的方法信息（包括：方法修饰符、方法名称、参数列表等等）。
//
//《定义》
//public final class Method extends AbstractMethod implements GenericDeclaration, Member
//在 JDK 中 java.lang.reflect.Method 和 java.lang.reflect.Constructor 都继承自 Executable，因此它俩也有同样的能力。
//
//《获取Method类对象》
//一共有4种方法,全部都在Class类中:
//
//1. getMethods(): 获得类的public类型的方法
//
//2. getMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型
//
//3. getDeclaredMethods(): 获取类中所有的方法(public、protected、default、private)
//
//4. getDeclaredMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型
//
//《常用方法》
/*class MethodDemo {
	public int addResult(Integer addNum) {
		return 2 + addNum;
	}

	public String toString() {
		return "asdasdasdasd";
	}
}

public class Method类1 {
	public static void main(String[] args) throws Exception {
		// 使用反射第一步:获取操作类MethodDemoFieldDemo所对应的Class对象
		Class<?> cls = Class.forName("反射.MethodDemo");
		// 使用MethodDemo类的class对象生成 实例
		Object obj = cls.newInstance();

		// 获取public int addResult(int addNum)方法
		Method addMethod = cls.getMethod("addResult", new Class[] { Integer.class });
		System.out.println("修饰符: " + Modifier.toString(addMethod.getModifiers()));//修饰符: public
		System.out.println("返回值: " + addMethod.getReturnType());//返回值: int
		System.out.println("方法名称: " + addMethod.getName());//方法名称: addResult
		System.out.println("参数列表: " + Arrays.toString(addMethod.getParameterTypes()));//参数列表: [class java.lang.Integer]
		int result = (int) addMethod.invoke(obj, 2);//调用addResult后的运行结果:4
		System.out.println("调用addResult后的运行结果:" + result);

		System.out.println("--------------------------------");

		// 获取public String toString() 方法
		Method toStringMethod = cls.getMethod("toString", new Class[] {});
		System.out.println("修饰符: " + Modifier.toString(toStringMethod.getModifiers()));//修饰符: public
		System.out.println("返回值: " + toStringMethod.getReturnType());//返回值: class java.lang.String
		System.out.println("方法名称: " + toStringMethod.getName());//方法名称: toString
		System.out.println("参数列表: " + Arrays.toString(toStringMethod.getParameterTypes()));//参数列表: []
		String msg = (String) toStringMethod.invoke(obj);
		System.out.println("调用toString后的运行结果:" + msg);//调用toString后的运行结果:asdasdasdasd
	}
}*/

//《Method.invoke()反射调用方法》
///** 
// * <p>java反射中Method类invoke方法的用法</p> * 
// */
//public class InvokeTester {
public class Method类1 {
    private String name;
    
    public Method类1() {}
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public int add(int param1, int param2) {
        return param1 + param2;
    }
    public String echo(String mesg) {
        return "echo" + mesg;
    }

    public static void main(String[] args) {
        Class<?> classType = Method类1.class;
        Method类1 invokertester=null;
        try {
//        	Object invokertester = classType.newInstance(); //1
            invokertester = (Method类1) classType.newInstance(); //1
            Method addMethod = classType.getMethod("add", new Class[] { //2  
                int.class,
                int.class
            });

            Object result = addMethod.invoke(invokertester, new Object[] { //3  
                Integer.valueOf(100),
                Integer.valueOf(200)
            });

            System.out.println(result); 
            Method echo = classType.getMethod("echo", new Class[] {
                String.class
            });
            Object obj = echo.invoke(invokertester, new Object[] {
                new String("jy is very good!!!")
            });
            System.out.println(obj.toString());

            Method类1 test = new Method类1(); //1  
            test.setName("黄翊"); //2  
            //Method[] methods;  
            Method[] methods = test.getClass().getDeclaredMethods(); //3  
            //循环查找获取id方法，并执行查看是否有返回值  
            for (int i = 0; i < methods.length; i++) {
                //如果此方法有get和Id关键字则执行  
                if (methods[i].getName().indexOf("get") != -1 && methods[i].getName().indexOf("Name") != -1) {
                    try {
                        // 获取此get方法返回值,判断是否有值,如果没有值说明即将执行的操作新增  
                        if (methods[i].invoke(test, null) == null) { //4                                             
                            System.out.println("此对象没有值！！！");
                        } else {
                            Object strName = methods[i].invoke(test, null);
                            System.out.println(strName);
                        }
                    } catch(Exception e) {
                        System.out.print("");
                    }
                }
            }
        } 
        catch(IllegalAccessException ex) {} 
        catch(InstantiationException ex) {} 
        catch(SecurityException ex) {} 
        catch(NoSuchMethodException ex) {} 
        catch(InvocationTargetException ex) {} 
        catch(IllegalArgumentException ex) {}
    }
}
//Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。
//invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回.
//
//例子
//public class MethodTypeSpy extends BaseTestClass {
//    private static final String fmt = "%24s:   %s\n";
//    private static final String HELLO_WORLD = "I'm cute shixin";
//    @Deprecated
//    public static void main(String[] args) throws ClassNotFoundException {
//        MethodTypeSpy methodTypeSpy = new MethodTypeSpy();
//        Class<? extends MethodTypeSpy> cls = methodTypeSpy.getClass();
//        printFormat("Class：%s \n", cls.getCanonicalName());
//        Method[] declaredMethods = cls.getDeclaredMethods();
//        for (Method declaredMethod : declaredMethods) {
//            printFormat(fmt, "Method name", declaredMethod.getName());  //获得单独的方法名
//            //获得完整的方法信息（包括修饰符、返回值、路径、名称、参数、抛出值）
//            printFormat(fmt, "toGenericString", declaredMethod.toGenericString());
//
//            int modifiers = declaredMethod.getModifiers();      //获得修饰符
//            printFormat(fmt, "Modifiers", Modifier.toString(modifiers));
//
//            System.out.format(fmt, "ReturnType", declaredMethod.getReturnType());   //获得返回值
//            System.out.format(fmt, "getGenericReturnType", declaredMethod.getGenericReturnType());//获得完整信息的返回值
//
//            Class<?>[] parameterTypes = declaredMethod.getParameterTypes(); //获得参数类型
//            Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
//            for (int i = 0; i < parameterTypes.length; i++) {
//                System.out.format(fmt, "ParameterType", parameterTypes[i]);
//                System.out.format(fmt, "GenericParameterType", genericParameterTypes[i]);
//            }
//
//            Class<?>[] exceptionTypes = declaredMethod.getExceptionTypes();     //获得异常名称
//            Type[] genericExceptionTypes = declaredMethod.getGenericExceptionTypes();
//            for (int i = 0; i < exceptionTypes.length; i++) {
//                System.out.format(fmt, "ExceptionTypes", exceptionTypes[i]);
//                System.out.format(fmt, "GenericExceptionTypes", genericExceptionTypes[i]);
//            }
//
//            Annotation[] annotations = declaredMethod.getAnnotations(); //获得注解
//            for (Annotation annotation : annotations) {
//                System.out.format(fmt, "Annotation", annotation);
//                System.out.format(fmt, "AnnotationType", annotation.annotationType());
//            }
//        }
//    }
//}
//运行结果：
//
//Class：net.sxkeji.shixinandroiddemo2.test.reflection.MethodTypeSpy 
//             Method name:   main
//         toGenericString:   public static void net.sxkeji.shixinandroiddemo2.test.reflection.MethodTypeSpy.main(java.lang.String[]) throws java.lang.ClassNotFoundException
//               Modifiers:   public static
//              ReturnType:   void
//    getGenericReturnType:   void
//           ParameterType:   class [Ljava.lang.String;
//    GenericParameterType:   class [Ljava.lang.String;
//          ExceptionTypes:   class java.lang.ClassNotFoundException
//   GenericExceptionTypes:   class java.lang.ClassNotFoundException
//              Annotation:   @java.lang.Deprecated()
//          AnnotationType:   interface java.lang.Deprecated
//
//Process finished with exit code 0
//权限总结
//1. public的static的方法：没有任何权限问题，getMethod()就可以满足，根本不用getDeclaredMethod出马，更不用setAccessiable(true)
//
//2. public的非静态的方法：没有任何权限问题，getMethod()就可以满足，根本不用getDeclaredMethod出马，更不用setAccessiable(true)，
//但是，在invoke时，第一个参数必须是具体的某一个对象，static的可要可不要
//
//3. protected的非静态方法：必须使用getDeclaredMethod，不能使用getMethod，不用设置setAccessiable(true)
//
//4. friendly的非静态方法：必须使用getDeclaredMethod，不能使用getMethod，不用设置setAccessiable(true)
//
//5. private的非静态方法：必须使用getDeclaredMethod，不能使用getMethod，必须设置setAccessiable(true)
